/* This source file is part of the ATMEL AVR32-SoftwareFramework-1.2.2ES-AT32UC3A
Release */

/*This file is prepared for Doxygen automatic documentation generation.*/
/*! \file ******************************************************************
 *
 * \brief Management of the USB device CDC task.
 *
 * This file manages the USB device CDC task.
 *
 * - Compiler:           IAR EWAVR32 and GNU GCC for AVR32
 * - Supported devices:  All AVR32 devices with a USB module can be used.
 * - AppNote:
 *
 * \author               Atmel Corporation: http://www.atmel.com \n
 *                       Support and FAQ: http://support.atmel.no/
 *
 ***************************************************************************/

/* Copyright (c) 2007, Atmel Corporation All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * 3. The name of ATMEL may not be used to endorse or promote products derived
 * from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY ATMEL ``AS IS'' AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY AND
 * SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */


//_____  I N C L U D E S ___________________________________________________

#if USB_DEVICE_FEATURE == ENABLED

#include "protocol_code.h"
#include "usb_drv.h"
#include <math.h>
//#include "..\..\..\ethernet.h"

#define NUL 0
#define SOH 1
#define STX 2
#define ETX 3
#define EOT 4
#define ENQ 5
#define ACK 6
#define BEL 7

#define DLE 16
#define NAK 21
#define ETB 23
#define CAN 24
#define ESC 27


static volatile U16  sof_cnt;

int count = 0;
int count1=0;
char pcReceived[20];
char serialRead[1001];
int stringPlace = 0;

//SERIAL TO USB
void ser2usb()
{
	serialRead[stringPlace] = '\0';
	sendUSBString(serialRead);
}




void device_cdc_task_init(void)
{
	sof_cnt   =0 ;
	uart_usb_init();

#ifndef FREERTOS_USED
#if USB_HOST_FEATURE == ENABLED
	// If both device and host features are enabled, check if device mode is engaged
	// (accessing the USB registers of a non-engaged mode, even with load operations,
	// may corrupt USB FIFO data).
	if (Is_usb_device())
#endif  // USB_HOST_FEATURE == ENABLED
		Usb_enable_sof_interrupt();
#endif  // FREERTOS_USED

#ifdef FREERTOS_USED
	xTaskCreate(device_cdc_task,
			configTSK_USB_DCDC_NAME,
			configTSK_USB_DCDC_STACK_SIZE,
			NULL,
			configTSK_USB_DCDC_PRIORITY,
			NULL);

#endif  // FREERTOS_USED
}

//!
//! @brief Entry point of the device CDC task management
//!
#ifdef FREERTOS_USED
void device_cdc_task(void *pvParameters)
#else
void device_cdc_task(void)
#endif
{
	int c;

	static Bool startup=TRUE;

#ifdef FREERTOS_USED
	portTickType xLastWakeTime;
	xLastWakeTime = xTaskGetTickCount();

	while (TRUE)
	{
		vTaskDelayUntil(&xLastWakeTime, configTSK_USB_DCDC_PERIOD);

		// First, check the device enumeration state
		if (!Is_device_enumerated()) continue;
#else
		// First, check the device enumeration state
		if (!Is_device_enumerated()) return;
#endif  // FREERTOS_USED

		if( startup )
		{
			//printf("\r\nRS232?\r\n");
			startup=FALSE;
		}
		if( sof_cnt>=NB_MS_BEFORE_FLUSH )  //Flush buffer in Timeout
		{
			sof_cnt=0;
			uart_usb_flush();
		}

		if(usart_test_hit(DBG_USART))    // Something on USART ?
		{

			if( stringPlace < 1000 && USART_SUCCESS==usart_read_char(DBG_USART, &c) )
			{
				serialRead[stringPlace] = c;
				stringPlace++;
				//uart_usb_putchar(c);
				//uart_usb_flush();

			}
			else {
				usart_reset_status( DBG_USART );
			}
		}



		if (uart_usb_test_hit())          // Something received from the PC ?
		{

			if( uart_usb_tx_ready() )
			{
				// uart_usb_putchar(uart_usb_getchar());  //LOOPBACK TEST for debug

				pcReceived[0]= uart_usb_getchar();
				//usart_putchar(DBG_USART,pcReceived[0]);
				pcReceived[1]= uart_usb_getchar();
				pcReceived[2]= uart_usb_getchar();
				pcReceived[3]= uart_usb_getchar();
				pcReceived[4]= '\0';
				if(strcmp(pcReceived,"INIT") == 0)
				{
					// TODO: check jumpers and any other startup config things
					//TODO: set all gpio header pins to open drain??????? then set/clr on each port's init
					gpio_enable_gpio_pin(AVR32_PIN_PA23);
					gpio_enable_pin_open_drain(AVR32_PIN_PA23);
					gpio_enable_gpio_pin(AVR32_PIN_PA27);
					gpio_enable_pin_open_drain(AVR32_PIN_PA27);
					gpio_enable_gpio_pin(AVR32_PIN_PA07);
					gpio_enable_pin_open_drain(AVR32_PIN_PA07);

					if (!gpio_get_pin_value(AVR32_PIN_PA07))
					{
						sendUSBString("No Serial present\n");
					}
					else
					{
						sendUSBString("Serial present\n");
					}
					if (!gpio_get_pin_value(AVR32_PIN_PA23))
					{
						sendUSBString("No GPIB present\n");
					}
					else
					{
						sendUSBString("GPIB present\n");
					}
					if (!gpio_get_pin_value(AVR32_PIN_PA27))
					{
						sendUSBString("No Parallel present\n");
					}
					else
					{
						sendUSBString("Parallel present\n");
					}
					sendUSBString("Board Initialized\n&");

				}
				else if(strcmp(pcReceived,"INTG") == 0)	//initialize GPIB Bus
				{
					init_GPIB();
					sendUSBString("GPIB Bus Initialized test\n&");
				}

				else if(strcmp(pcReceived,"INTP") == 0)	//initialize parallel port
				{
					// TODO: call parallel init code and setup mode

					pcReceived[0]= uart_usb_getchar();
					pcReceived[1]= uart_usb_getchar();
					pcReceived[2]= uart_usb_getchar();
					pcReceived[3]= '\0';
					sendUSBString(pcReceived);
					sendUSBString("&");

				}

				else if(strcmp(pcReceived,"INTS") == 0)	//initialize serial port
				{

					char baudString[7], parityString, stopbitsString;
					int baud;
					static usart_options_t dbg_usart_options;
					U32 stopbits, parity;
					int i;

					int baudStringSize = uart_usb_getchar() - 48;	//1 digit baud string length
					for(i = 0; i <baudStringSize; i++)
					{
						//baud = (uart_usb_getchar()-48) * (pow(10,baudStringSize-1-i));
						baudString[i] = uart_usb_getchar();
					}
					baudString[i] = '\0';
					baud = atoi(baudString);
					parityString = uart_usb_getchar();
					stopbitsString = uart_usb_getchar();

					switch(parityString)
					{
					case 'E':
					case 'e':
						parity = AVR32_USART_MR_PAR_EVEN;   //!< Use even parity on character transmission.
						break;
					case 'O':
					case 'o':
						parity = AVR32_USART_MR_PAR_ODD;    //!< Use odd parity on character transmission.
						break;
					case 'S':
					case 's':
						parity = AVR32_USART_MR_PAR_SPACE;  //!< Use a space as parity bit.
						break;
					case 'M':
					case 'm':
						parity = AVR32_USART_MR_PAR_MARK;   //!< Use a mark as parity bit.
						break;
					case 'N':
					case 'n':
						parity = AVR32_USART_MR_PAR_NONE;   //!< Don't use a parity bit.
						break;
					default:	//guaranteed not to occur by C-api
						break;
					}
					switch(stopbitsString)
					{
					case '1':
						stopbits = AVR32_USART_MR_NBSTOP_1;   //!< Use 1 stop bit.
						break;
					case '0':
						stopbits = AVR32_USART_MR_NBSTOP_1_5; //!< Use 1.5 stop bits.
						break;
					case '2':
						stopbits = AVR32_USART_MR_NBSTOP_2;   //!< Use 2 stop bits
						break;
					default:
						stopbits = stopbitsString-48;   //!< (for more, just give the number of bits).
						break;
					}

					// Options for serial usart
					//user defined
					dbg_usart_options.baudrate    = baud;
					dbg_usart_options.paritytype  = parity;
					dbg_usart_options.stopbits    = stopbits;
					//preset
					dbg_usart_options.charlength  = 8;//Usb_read_endpoint_data(EP_CONTROL, 8);
					dbg_usart_options.channelmode = AVR32_USART_MR_CHMODE_NORMAL ;

					// Initialize usart
					usart_init_rs232(&AVR32_USART1, &dbg_usart_options, FOSC0);
					char srlParam[70];
					//strcpy(srlParam, "@Serial Port initialized to baud: ");
					//char baudParsedStr[10];
					sprintf(srlParam, "Serial Port initialized to baud:%d, parity:%c, stopbits:%c\n&", baud, parityString, stopbitsString);
					sendUSBString(srlParam);
				}



				else if(strcmp(pcReceived,"GPIB") == 0)			//gpib data/cmd
				{
					sendUSBString("GPIB Port:");
					pcReceived[0]= uart_usb_getchar();	//get R or W for read/write

					if( pcReceived[0] == 'F')	//Read
					{  sendUSBString("Wavefrm:");
					if(readGPIBWF() != 0)
						sendUSBString(" ReadF  Failed\n&");
					else
						sendUSBString(" ReadF Success\n&");
					//uart_usb_getchar();uart_usb_getchar();uart_usb_getchar();uart_usb_getchar();uart_usb_getchar();
					}
					else if( pcReceived[0] == 'R')	//Read
					{  sendUSBString("Reading:");
					if(readGPIB() != 0)
						sendUSBString(" Read   Failed\n&");
					else
						sendUSBString(" Read  Success\n&");
					//uart_usb_getchar();uart_usb_getchar();uart_usb_getchar();uart_usb_getchar();uart_usb_getchar();
					}
					else if( pcReceived[0] == 'W')	//Write
					{  sendUSBString("Writing:");
					if(sendGPIBData() != 0)
						sendUSBString("Write   Failed\n&");
					else
						sendUSBString("Write  Success\n&");
					// uart_usb_getchar();
					}
					else
						sendUSBString("Unkwn GPIB cmd\n&");
				}

				else if(strcmp(pcReceived,"PARL") == 0)			//parallel data
				{
					sendUSBString("PARL Port:");
					// while(uart_usb_test_hit()) {uart_usb_putchar(uart_usb_getchar());}  //LOOPBACK TEST for debug
					pcReceived[0]= uart_usb_getchar();	//get R or W for read/write
					if( pcReceived[0] == 'R')	//Read
					{
						sendUSBString("Reading: \n");
						//TODO: add code
						setupParallelRead();
						int started = 0;
						//gpio_clr_gpio_pin(BUSY);
						int timeout = 0;
						int timeout1 = 0;
						while(1){
							//clear busy to start receiving
							gpio_clr_gpio_pin(BUSY);

							//wait for nStrobe with timeout
							while(gpio_get_pin_value(nSTROBE))
							{
								timeout++;
								if(timeout == 99999)
								{
									timeout = 0;
									timeout1++;
									if(timeout1 == 100)
										goto done;
								}
							}
							gpio_set_gpio_pin(BUSY);	//indicate busy to sender
							//reset timeouts
							timeout = 0;
							timeout1= 0;



							//if(started == 0) {sendUSBString("@");	started = 1;}   //indicate to C-api that file is starting

							//uart_usb_flush();
							uart_usb_putchar(binaryToAsciiPar( createDataCharParallel()));
							uart_usb_flush();
						}
						done:
						sendUSBString(" Read  Success\n&");
					}
					else if( pcReceived[0] == 'W')	//Write
					{
						sendUSBString("Writing:");
						setupParallelWrite();
						usb2par();		//writes until '/r'
						sendUSBString("Write  Success\n&");
					}
					else
					{
						sendUSBString("Unkwn PARL cmd\n&");
					}

				}


				else if(strcmp(pcReceived,"SERL") == 0)			//serial data
				{
					sendUSBString("SERL Port:");
					//call serial code
					pcReceived[0]= uart_usb_getchar();	//get R or W for read/write
					if( pcReceived[0] == 'R')	//Read
					{
						sendUSBString("Reading:");
						int started = 0;
						//gpio_clr_gpio_pin(BUSY);
						int timeout = 0;
						int timeout1 = 0;
						int end = 0;
						if(stringPlace > 0)
						{
							//sendUSBString("@");
							ser2usb();	//READS  back stored chars(upto 1000) from buffer serialRead
							stringPlace=0;
							started = 1;
						}//indicate to C-api that file is starting

						while (end == 0)
						{
							timeout++;
							if(timeout == 99999)
							{//sendUSBString("k");
								timeout1++;
								if(timeout1 == 50)
								{
									end = 1;
								}
								timeout = 0;
							}
							while(usart_test_hit(DBG_USART))    // Something on USART ?
							{
								//if(started == 0) {sendUSBString("@");	started = 1;}//indicate to C-api that file is starting
								timeout=0;
								if(USART_SUCCESS==usart_read_char(DBG_USART, &c) )
								{
									//if(c=='&') {	end=1; break;}
									serialRead[stringPlace] = c;
									stringPlace++;
								}
								else
								{
									usart_reset_status( DBG_USART );
								}
								if(stringPlace > 10)
								{
									ser2usb();	//send buffer to c-api when reach 400
									stringPlace=0;
								}
							}
						}
						ser2usb();	//READS  back any remaining serial chars
						stringPlace=0;
						sendUSBString(" Read  Success\n&");
					}
					else if( pcReceived[0] == 'W')	//Write
					{
						//usart_putchar(DBG_USART,'W');
						sendUSBString("Writing:");
						usb2ser();		//writes until '\n'
						sendUSBString("Write  Success\n&");
					}
					else
					{
						sendUSBString("Unkwn SRL cmd\n&");
					}
				}
				/*else if(strcmp(pcReceived,"ETHR") == 0)			//serial data
			{
				  sendUSBString("Ethernet:");
				  //call serial code
				  pcReceived[0]= uart_usb_getchar();	//get R or W for read/write
				  if( pcReceived[0] == 'R')	//Read
				  {
					  sendUSBString("Reading:");
					  unsigned long len, i = 0;
					  macb_packet_t recvd_pkt;
					  // do a loop, and display stats or quit
					    while (1)
					    {
					      // Loop while no data are pending.
					      vMACBWaitForInput(100);
					      // Obtain the size of the packet.
					      len = ulMACBInputLength();
					      if( len != 0)
					      {
					        // Let the driver know we are going to read a new packet.
					        vMACBRead( NULL, 0, 0 );
					        // Read enough bytes to fill this buf.
					        vMACBRead( data, 128, len );
					        recvd_pkt.data = data;
					        recvd_pkt.len = len;
					        macb_example_receive_packet(&recvd_pkt);
					      }
					      if (++i >= 400)
					      {
					        i = 0;
					        // send ARP request to host
					        macb_example_send_ARP_request();
					      }
					    }

				  }
				  else if( pcReceived[0] == 'W')	//Write
				  {
					  sendUSBString("Writing:");

				  }
				  else
				  {
					  sendUSBString("Unrecognized ethernet command");
				  }
			}*/
				else
				{
					sendUSBString("\n\nUnknwn port\n");
					int i = 0;
					for(i=0;i<10;i++)
					{
						uart_usb_putchar(pcReceived[i]);
					}
					sendUSBString("\nData Ignored &");
				}

			}
		}



#ifdef FREERTOS_USED
	}
#endif
}


//!
//! @brief usb_sof_action
//!
//! This function increments the sof_cnt counter each time
//! the USB Start-of-Frame interrupt subroutine is executed (1 ms).
//! Useful to manage time delays
//!
void usb_sof_action(void)
{
	sof_cnt++;
}
#endif  // USB_DEVICE_FEATURE == ENABLED

